package com.hula.onion.book.server.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.hula.onion.book.server.common.CommonResponse;
import com.hula.onion.book.server.config.ChannelConfig;
import com.hula.onion.book.server.config.JedisUtils;
import com.hula.onion.book.server.config.ResponseStatusEnum;
import com.hula.onion.book.server.config.SmsCodeConfig;
import com.hula.onion.book.server.dao.IUserDao;
import com.hula.onion.book.server.model.User;
import com.hula.onion.book.server.service.UserService;
import com.hula.onion.book.server.utils.HttpUtils;
import com.hula.onion.book.server.utils.SmsUtils;
import com.hula.onion.book.server.vo.UserVo;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.Map;

/**
 * Created by shan on 18/1/24.
 */
@Service
public class UserServiceImpl implements UserService {

    @Autowired
    private IUserDao userDao;

    private static final String VERIFY_CODE_PRE = "【洋葱记账】您的验证码是:";
    private static final String VERIFY_CODE_POST = "，有效期3分钟；如非本人操作,请忽略本消息。";
    private static final String REGISTER_CODE_PRE = "【洋葱记账】恭喜您注册成功，您的初始密码:";
    private static final String REGISTER_CODE_END = ",请尽快修改密码；如非本人操作,请忽略本消息。";
    private static final long CACHE_TIME = 3 * 60 * 1000;
    private static final String LITTLE_WX_APPID = "wxc8523abf72921800";
    private static final String LITTLE_WX_SECRET = "41beba40a19940ac171a3726a7f587ae";

    @Override
    public CommonResponse openIdLogin(String nickName, String headPic, String openId, int source) {
        if(StringUtils.isEmpty(openId)){
            return new CommonResponse(ResponseStatusEnum.PARAMS_ERROR);
        }
        User user = userDao.getUserByOpendId(openId, source);
        if (user != null) {
            if (ChannelConfig.WECHAT.getValue() == source) {
                if (nickName != user.getWxNickName() || headPic != user.getWxHeadPic()) {
                    //更新昵称和头像
                    userDao.updateUser(nickName, headPic, user.getId(), source);
                    user.setWxNickName(nickName);
                    user.setWxHeadPic(headPic);
                }
            } else if (ChannelConfig.QQ.getValue() == source) {
                if (nickName != user.getQqNickName() || headPic != user.getQqHeadPic()) {
                    //更新昵称和头像
                    userDao.updateUser(nickName, headPic, user.getId(), source);
                    user.setQqNickName(nickName);
                    user.setQqHeadPic(headPic);
                }
            }
            return new CommonResponse(new UserVo(user));
        }
        //新用户注册
        int id = userDao.register(nickName, headPic, openId, source);
        if (id > 0) {
            UserVo userVo = new UserVo();
            userVo.setId(id);
            userVo.setPhone("");
            if (ChannelConfig.WECHAT.getValue() == source) {
                userVo.setWxOpenid(openId);
                userVo.setWxHeadPic(headPic);
                userVo.setWxNickName(nickName);
            } else if (ChannelConfig.QQ.getValue() == source) {
                userVo.setQqOpenid(openId);
                userVo.setQqNickName(nickName);
                userVo.setQqHeadPic(headPic);
            }
            userVo.setChannelId(source);
            return new CommonResponse(userVo);
        }
        return new CommonResponse(ResponseStatusEnum.DATABASE_ERROR);
    }


    @Override
    public CommonResponse sendVerifyCode(String mobile, int codeType, String md5Code) {
        SmsCodeConfig smsCodeType = SmsCodeConfig.findByValue(codeType);
        if (smsCodeType != null) {
            if (!md5Code.equals(DigestUtils.md5Hex("yangcong" + mobile))) {
                return new CommonResponse(ResponseStatusEnum.SMS_CODE_SIGIN_FAIL);
            }
            if (smsCodeType.name().equals(SmsCodeConfig.REGISTER.name())) {
                if (userDao.mobileExist(mobile)) {
                    return new CommonResponse(ResponseStatusEnum.MOBILE_ALREADY_REGIST);
                }
            }
            this.sendCode(mobile);
        } else {
            return new CommonResponse(ResponseStatusEnum.SMS_CODE_TYPE_FAIL);
        }
        return new CommonResponse();
    }

    @Override
    public CommonResponse register(String verifyCode, String mobile, String password) {
        if (!verifyTheCode(mobile, verifyCode)) {
            return new CommonResponse(ResponseStatusEnum.VERIFY_CODE_FAIL);
        }
        String encrptedPassword = DigestUtils.md5Hex(password);
        boolean result = userDao.register(mobile, encrptedPassword);
        if (!result) {
            return new CommonResponse(ResponseStatusEnum.DATABASE_ERROR);
        }
        User user = userDao.getUserByMobile(mobile);
        UserVo userVo = new UserVo(user);
        userVo.setChannelId(ChannelConfig.PHONE.getValue());
        return new CommonResponse(userVo);
    }

    @Override
    public CommonResponse forgetPassword(String verifyCode, String mobile, String newPassword) {
        if (!verifyTheCode(mobile, verifyCode)) {
            return new CommonResponse(ResponseStatusEnum.VERIFY_CODE_FAIL);
        }
        String encrptedPassword = DigestUtils.md5Hex(newPassword);
        boolean result = userDao.updatePassword(mobile, encrptedPassword);
        if (!result) {
            return new CommonResponse(ResponseStatusEnum.DATABASE_ERROR);
        }
        return new CommonResponse();
    }

    @Override
    public CommonResponse pwdLogin(String mobile, String password) {
        User user = userDao.getUserByMobile(mobile);
        if (user == null) {
            return new CommonResponse(ResponseStatusEnum.USER_NOT_EXIST);
        }
        String encrpytPassword = DigestUtils.md5Hex(password);
        if (!encrpytPassword.equals(user.getPassword())) {
            return new CommonResponse(ResponseStatusEnum.PASSWORD_ERROR);
        }
        UserVo userVo = new UserVo(user);
        return new CommonResponse(userVo);
    }


    @Override
    public CommonResponse codeLogin(String mobile, String verifyCode) {

        if (!verifyTheCode(mobile, verifyCode)) {
            return new CommonResponse(ResponseStatusEnum.VERIFY_CODE_FAIL);
        }
        User user = userDao.getUserByMobile(mobile);
        if (user == null) {
            int smsCode = (int) ((Math.random() * 9 + 1) * 100000);
            String pwd = DigestUtils.md5Hex(String.valueOf(smsCode));
            userDao.register(mobile, DigestUtils.md5Hex(pwd));
            SmsUtils.sendMsg(mobile, REGISTER_CODE_PRE + smsCode + REGISTER_CODE_END);
            user = userDao.getUserByMobile(mobile);
        }
        UserVo userVo = new UserVo(user);
        userVo.setChannelId(ChannelConfig.PHONE.getValue());
        return new CommonResponse(userVo);
    }


    @Override
    public CommonResponse changePassword(int userId, String oldPassword, String newPassword) {
        String userPassword = userDao.getPasswordByUid(userId);
        if (!userPassword.equals(DigestUtils.md5Hex(oldPassword))) {
            return new CommonResponse(ResponseStatusEnum.PASSWORD_ERROR);
        }
        boolean result = userDao.changePasswordByUid(userId,
                DigestUtils.md5Hex(newPassword));
        if (!result) {
            return new CommonResponse(ResponseStatusEnum.DATABASE_ERROR);
        }
        return new CommonResponse();
    }

    @Override
    public CommonResponse bindPhone(int userId, String verifyCode, String mobile, String password) {
        if (!verifyTheCode(mobile, verifyCode)) {
            return new CommonResponse(ResponseStatusEnum.VERIFY_CODE_FAIL);
        }
        String encrptedPassword = DigestUtils.md5Hex(password);
        boolean result = userDao.bindPhone(userId, mobile, encrptedPassword);
        if (!result) {
            return new CommonResponse(ResponseStatusEnum.DATABASE_ERROR);
        }
        return new CommonResponse();
    }

    @Override
    public CommonResponse bindThird(int userId, String openId, String nickName, String headPic, int source) {
        User oldUser = userDao.getUserByOpendId(openId, source);
        if (oldUser != null) {
            if (ChannelConfig.WECHAT.getValue() == source) {
                return new CommonResponse(ResponseStatusEnum.WHCHAT_EXIST);
            } else if (ChannelConfig.QQ.getValue() == source) {
                return new CommonResponse(ResponseStatusEnum.QQ_EXIST);
            }
        }
        boolean result = userDao.bindThird(userId, openId, nickName, headPic, source);
        if (result) {
            User user = userDao.getUserByUserId(userId);
            return new CommonResponse(new UserVo(user));
        }
        return new CommonResponse(ResponseStatusEnum.DATABASE_ERROR);
    }

    private boolean verifyTheCode(String mobile, String code) {
        if (StringUtils.isEmpty(code)) {
            return false;
        }
        String cacheCode = JedisUtils.getInstance().get(mobile);
        if (code.equals(cacheCode)) {
            JedisUtils.getInstance().del(mobile);
            return true;
        }
        return false;
    }


    private boolean sendCode(String mobile) {
        int smsCode = (int) ((Math.random() * 9 + 1) * 100000);
        String content = VERIFY_CODE_PRE + smsCode + VERIFY_CODE_POST;
        boolean result = SmsUtils.sendMsg(mobile, content);
        if (result) {//放入redis缓存
            JedisUtils.getInstance().set(mobile, String.valueOf(smsCode),
                    CACHE_TIME);
        }
        return result;
    }

    @Override
    public CommonResponse createFeedBack(int userId, String message) {
        boolean result = userDao.createFeedBack(userId, message);
        if (!result) {
            return new CommonResponse(ResponseStatusEnum.DATABASE_ERROR);
        }
        return new CommonResponse();
    }

    @Override
    public CommonResponse littleWxLogin(String code) {
        if (StringUtils.isEmpty(code)) {
            return new CommonResponse(ResponseStatusEnum.PARAMS_ERROR);
        }
        Map<String, Object> params = new HashMap<>();
        params.put("appid", LITTLE_WX_APPID);
        params.put("secret", LITTLE_WX_SECRET);
        params.put("grant_type", "authorization_code");
        params.put("js_code", code);
        String result = HttpUtils.get("https://api.weixin.qq.com/sns/jscode2session",
                params, null);
        if (StringUtils.isNotEmpty(result)) {
            JSONObject resultJson = JSON.parseObject(result);
            if (resultJson.containsKey("unionid")) {
                CommonResponse commonResponse = new CommonResponse();
                commonResponse.setData(resultJson.getString("unionid"));
                return commonResponse;
            } else {
                CommonResponse commonResponse = new CommonResponse(ResponseStatusEnum.FAIL);
                commonResponse.setMsg(resultJson.getString("errmsg"));
                return commonResponse;
            }
        }
        return new CommonResponse(ResponseStatusEnum.FAIL);
    }
}
